home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / GCC 1.37.1r14 / usr / gcc-1.37.1r14 / non-obj files / cplus-dem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-12  |  17.1 KB  |  924 lines  |  [TEXT/CPED]

  1. /* Demangler for GNU C++ 
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.    written by James Clark (jjc@jclark.uucp)
  4.    
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 1, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /* This is for g++ 1.36.1 (November 6 version). It will probably
  20.    require changes for any other version. */
  21.  
  22. /* This file exports one function
  23.  
  24.    char *cplus_demangle (const char *name)
  25.    
  26.    If `name' is a mangled function name produced by g++, then
  27.    a pointer to a malloced string giving a C++ representation
  28.    of the name will be returned; otherwise NULL will be returned.
  29.    It is the caller's responsibility to free the string which
  30.    is returned.
  31.  
  32.    For example,
  33.    
  34.    cplus_demangle ("_foo__1Ai")
  35.    
  36.    returns
  37.  
  38.    "A::foo(int)"
  39.  
  40.    This file imports xmalloc and xrealloc, which are like malloc and
  41.    realloc except that they generate a fatal error if there is no
  42.    available memory. */
  43.  
  44. /* #define nounderscore 1 /* define this is names don't start with _ */
  45.  
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <ctype.h>
  49.  
  50. #define memcpy(s1, s2, n) strncpy(s1, s2, n) 
  51. #define memcmp(s1, s2, n) strncmp(s1, s2, n)
  52. #define strchr(s, c) index(s, c) 
  53.  
  54. #ifndef __STDC__
  55. #define const
  56. #endif
  57.  
  58. #ifdef __STDC__
  59. extern char *cplus_demangle (const char *type);
  60. #else
  61. extern char *cplus_demangle ();
  62. #endif
  63.  
  64. #ifndef xmalloc
  65. #ifdef __STDC__
  66. extern char *xmalloc (int);
  67. extern char *xrealloc (char *, int);
  68. #else
  69. extern char *xmalloc ();
  70. extern char *xrealloc ();
  71. #endif
  72. #endif
  73.  
  74. static char **typevec = 0;
  75. static int ntypes = 0;
  76. static int typevec_size = 0;
  77.  
  78. static struct {
  79.   const char *in;
  80.   const char *out;
  81. } optable[] = {
  82.   "new", " new",
  83.   "delete", " delete",
  84.   "ne", "!=",
  85.   "eq", "==",
  86.   "ge", ">=",
  87.   "gt", ">",
  88.   "le", "<=",
  89.   "lt", "<",
  90.   "plus", "+",
  91.   "minus", "-",
  92.   "mult", "*",
  93.   "negate", "-",
  94.   "trunc_mod", "%",
  95.   "trunc_div", "/",
  96.   "truth_andif", "&&",
  97.   "truth_orif", "||",
  98.   "postincrement", "++",
  99.   "postdecrement", "--",
  100.   "bit_ior", "|",
  101.   "bit_xor", "^",
  102.   "bit_and", "&",
  103.   "bit_not", "~",
  104.   "call", "()",
  105.   "cond", "?:",
  106.   "alshift", "<<",
  107.   "arshift", ">>",
  108.   "component", "->",
  109.   "nop", "",            /* for operator= */
  110. };
  111.  
  112. /* Beware: these aren't '\0' terminated. */
  113.  
  114. typedef struct {
  115.   char *b;            /* pointer to start of string */
  116.   char *p;            /* pointer after last character */
  117.   char *e;            /* pointer after end of allocated space */
  118. } string;
  119.  
  120. #ifdef __STDC__
  121. static void string_need (string *s, int n);
  122. static void string_delete (string *s);
  123. static void string_init (string *s);
  124. static void string_clear (string *s);
  125. static int string_empty (string *s);
  126. static void string_append (string *p, const char *s);
  127. static void string_appends (string *p, string *s);
  128. static void string_appendn (string *p, const char *s, int n);
  129. static void string_prepend (string *p, const char *s);
  130. #if 0
  131. static void string_prepends (string *p, string *s);
  132. #endif
  133. static void string_prependn (string *p, const char *s, int n);
  134. static int get_count (const char **type, int *count);
  135. static int do_args (const char **type, string *decl);
  136. static int do_type (const char **type, string *result);
  137. static int do_arg (const char **type, string *result);
  138. static int do_args (const char **type, string *decl);
  139. static void munge_function_name (string *name);
  140. #else
  141. static void string_need ();
  142. static void string_delete ();
  143. static void string_init ();
  144. static void string_clear ();
  145. static int string_empty ();
  146. static void string_append ();
  147. static void string_appends ();
  148. static void string_appendn ();
  149. static void string_prepend ();
  150. static void string_prepends ();
  151. static void string_prependn ();
  152. static int get_count ();
  153. static int do_args ();
  154. static int do_type ();
  155. static int do_arg ();
  156. static int do_args ();
  157. static void munge_function_name ();
  158. #endif
  159.  
  160. char *
  161. cplus_demangle (type)
  162.      const char *type;
  163. {
  164.   string decl;
  165.   int n;
  166.   int success = 0;
  167.   int constructor = 0;
  168.   int const_flag = 0;
  169.   int i;
  170.   const char *p;
  171.  
  172.   if (type == NULL || *type == '\0')
  173.     return NULL;
  174. #ifndef nounderscore
  175.   if (*type++ != '_')
  176.     return NULL;
  177. #endif
  178.   p = type;
  179.   while (*p != '\0' && !(*p == '_' && p[1] == '_'))
  180.     p++;
  181.   if (*p == '\0')
  182.     {
  183.       /* destructor */
  184.       if (type[0] == '_' && type[1] == '$' && type[2] == '_')
  185.     {
  186.       int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
  187.       char *tem = (char *) xmalloc (n);
  188.       strcpy (tem, type + 3);
  189.       strcat (tem, "::~");
  190.       strcat (tem, type + 3);
  191.       strcat (tem, "()");
  192.       return tem;
  193.     }
  194.       /* static data member */
  195.       if (*type != '_' && (p = strchr (type, '$')) != '\0')
  196.     {
  197.       int n = strlen (type) + 2;
  198.       char *tem = (char *) xmalloc (n);
  199.       memcpy (tem, type, p - type);
  200.       strcpy (tem + (p - type), "::");
  201.       strcpy (tem + (p - type) + 2, p + 1);
  202.       return tem;
  203.     }
  204.       return NULL;
  205.     }
  206.  
  207.   string_init (&decl);
  208.  
  209.   if (p == type)
  210.     {
  211.       if (!isdigit (p[2]))
  212.     {
  213.       string_delete (&decl);
  214.       return NULL;
  215.     }
  216.       constructor = 1;
  217.     }
  218.   else
  219.     {
  220.       string_appendn (&decl, type, p - type);
  221.       munge_function_name (&decl);
  222.     }
  223.   p += 2;
  224.  
  225.   switch (*p)
  226.     {
  227.     case 'C':
  228.       /* a const member function */
  229.       if (!isdigit (p[1]))
  230.     {
  231.       string_delete (&decl);
  232.       return NULL;
  233.     }
  234.       p += 1;
  235.       const_flag = 1;
  236.       /* fall through */
  237.     case '0':
  238.     case '1':
  239.     case '2':
  240.     case '3':
  241.     case '4':
  242.     case '5':
  243.     case '6':
  244.     case '7':
  245.     case '8':
  246.     case '9':
  247.       n = 0;
  248.       do
  249.     {
  250.       n *= 10;
  251.       n += *p - '0';
  252.       p += 1;
  253.     }
  254.       while (isdigit (*p));
  255.       if (strlen (p) < n)
  256.     {
  257.       string_delete (&decl);
  258.       return NULL;
  259.     }
  260.       if (constructor)
  261.     {
  262.       string_appendn (&decl, p, n);
  263.       string_append (&decl, "::");
  264.       string_appendn (&decl, p, n);
  265.     }
  266.       else
  267.     {
  268.       string_prepend (&decl, "::");
  269.       string_prependn (&decl, p, n);
  270.     }
  271.       p += n;
  272.       success = do_args (&p, &decl);
  273.       if (const_flag)
  274.     string_append (&decl, " const");
  275.       break;
  276.     case 'F':
  277.       p += 1;
  278.       success = do_args (&p, &decl);
  279.       break;
  280.     }
  281.  
  282.   for (i = 0; i < ntypes; i++)
  283.     if (typevec[i] != NULL)
  284.       free (typevec[i]);
  285.   ntypes = 0;
  286.   if (typevec != NULL)
  287.     {
  288.       free ((char *)typevec);
  289.       typevec = NULL;
  290.       typevec_size = 0;
  291.     }
  292.  
  293.   if (success)
  294.     {
  295.       string_appendn (&decl, "", 1);
  296.       return decl.b;
  297.     }
  298.   else
  299.     {
  300.       string_delete (&decl);
  301.       return NULL;
  302.     }
  303. }
  304.  
  305. static int
  306. get_count (type, count)
  307.      const char **type;
  308.      int *count;
  309. {
  310.   if (!isdigit (**type))
  311.     return 0;
  312.   *count = **type - '0';
  313.   *type += 1;
  314.   /* see flush_repeats in cplus-method.c */
  315.   if (isdigit (**type))
  316.     {
  317.       const char *p = *type;
  318.       int n = *count;
  319.       do 
  320.     {
  321.       n *= 10;
  322.       n += *p - '0';
  323.       p += 1;
  324.     } 
  325.       while (isdigit (*p));
  326.       if (*p == '_')
  327.     {
  328.       *type = p + 1;
  329.       *count = n;
  330.     }
  331.     }
  332.   return 1;
  333. }
  334.  
  335. /* result will be initialised here; it will be freed on failure */
  336.  
  337. static int
  338. do_type (type, result)
  339.      const char **type;
  340.      string *result;
  341. {
  342.   int n;
  343.   int done;
  344.   int non_empty;
  345.   int success;
  346.   string decl;
  347.   const char *remembered_type;
  348.  
  349.   string_init (&decl);
  350.   string_init (result);
  351.  
  352.   done = 0;
  353.   success = 1;
  354.   while (success && !done)
  355.     {
  356.       int member;
  357.       switch (**type)
  358.     {
  359.     case 'P':
  360.       *type += 1;
  361.       string_prepend (&decl, "*");
  362.       break;
  363.  
  364.     case 'R':
  365.       *type += 1;
  366.       string_prepend (&decl, "&");
  367.       break;
  368.  
  369.     case 'T':
  370.       *type += 1;
  371.       if (!get_count (type, &n) || n >= ntypes)
  372.         success = 0;
  373.       else
  374.         {
  375.           remembered_type = typevec[n];
  376.           type = &remembered_type;
  377.         }
  378.       break;
  379.  
  380.     case 'F':
  381.       *type += 1;
  382.       if (!string_empty (&decl) && decl.b[0] == '*')
  383.         {
  384.           string_prepend (&decl, "(");
  385.           string_append (&decl, ")");
  386.         }
  387.       if (!do_args (type, &decl) || **type != '_')
  388.         success = 0;
  389.       else
  390.         *type += 1;
  391.       break;
  392.  
  393.     case 'M':
  394.     case 'O':
  395.       {
  396.         int constp = 0;
  397.         int volatilep = 0;
  398.  
  399.         member = **type == 'M';
  400.         *type += 1;
  401.         if (!isdigit (**type))
  402.           {
  403.         success = 0;
  404.         break;
  405.           }
  406.         n = 0;
  407.         do
  408.           {
  409.         n *= 10;
  410.         n += **type - '0';
  411.         *type += 1;
  412.           } 
  413.         while (isdigit (**type));
  414.         if (strlen (*type) < n)
  415.           {
  416.         success = 0;
  417.         break;
  418.           }
  419.         string_append (&decl, ")");
  420.         string_prepend (&decl, "::");
  421.         string_prependn (&decl, *type, n);
  422.         string_prepend (&decl, "(");
  423.         *type += n;
  424.         if (member)
  425.           {
  426.         if (**type == 'C')
  427.           {
  428.             *type += 1;
  429.             constp = 1;
  430.           }
  431.         if (**type == 'V')
  432.           {
  433.             *type += 1;
  434.             volatilep = 1;
  435.           }
  436.         if (*(*type)++ != 'F')
  437.           {
  438.             success = 0;
  439.             break;
  440.           }
  441.           }
  442.         if ((member && !do_args (type, &decl)) || **type != '_')
  443.           {
  444.         success = 0;
  445.         break;
  446.           }
  447.         *type += 1;
  448.         if (constp)
  449.           {
  450.         if (non_empty)
  451.           string_append (&decl, " ");
  452.         else
  453.           non_empty = 1;
  454.         string_append (&decl, "const");
  455.           }
  456.         if (volatilep)
  457.           {
  458.         if (non_empty)
  459.           string_append (&decl, " ");
  460.         else
  461.           non_empty = 1;
  462.         string_append (&decl, "volatilep");
  463.           }
  464.         break;
  465.       }
  466.  
  467.     case 'C':
  468.       if ((*type)[1] == 'P')
  469.         {
  470.           *type += 1;
  471.           if (!string_empty (&decl))
  472.         string_prepend (&decl, " ");
  473.           string_prepend (&decl, "const");
  474.           break;
  475.         }
  476.  
  477.       /* fall through */
  478.     default:
  479.       done = 1;
  480.       break;
  481.     }
  482.     }
  483.  
  484.   done = 0;
  485.   non_empty = 0;
  486.   while (success && !done)
  487.     {
  488.       switch (**type)
  489.     {
  490.     case 'C':
  491.       *type += 1;
  492.       if (non_empty)
  493.         string_append (result, " ");
  494.       else
  495.         non_empty = 1;
  496.       string_append (result, "const");
  497.       break;
  498.     case 'U':
  499.       *type += 1;
  500.       if (non_empty)
  501.         string_append (result, " ");
  502.       else
  503.         non_empty = 1;
  504.       string_append (result, "unsigned");
  505.       break;
  506.     case 'V':
  507.       *type += 1;
  508.       if (non_empty)
  509.         string_append (result, " ");
  510.       else
  511.         non_empty = 1;
  512.       string_append (result, "volatile");
  513.       break;
  514.     default:
  515.       done = 1;
  516.       break;
  517.     }
  518.     }
  519.  
  520.   if (success)
  521.     switch (**type)
  522.       {
  523.       case '\0':
  524.       case '_':
  525.     break;
  526.       case 'v':
  527.     *type += 1;
  528.     if (non_empty)
  529.       string_append (result, " ");
  530.     string_append (result, "void");
  531.     break;
  532.       case 'l':
  533.     *type += 1;
  534.     if (non_empty)
  535.       string_append (result, " ");
  536.     string_append (result, "long");
  537.     break;
  538.       case 'i':
  539.     *type += 1;
  540.     if (non_empty)
  541.       string_append (result, " ");
  542.     string_append (result, "int");
  543.     break;
  544.       case 's':
  545.     *type += 1;
  546.     if (non_empty)
  547.       string_append (result, " ");
  548.     string_append (result, "short");
  549.     break;
  550.       case 'c':
  551.     *type += 1;
  552.     if (non_empty)
  553.       string_append (result, " ");
  554.     string_append (result, "char");
  555.     break;
  556.       case 'r':
  557.     *type += 1;
  558.     if (non_empty)
  559.       string_append (result, " ");
  560.     string_append (result, "long double");
  561.     break;
  562.       case 'd':
  563.     *type += 1;
  564.     if (non_empty)
  565.       string_append (result, " ");
  566.     string_append (result, "double");
  567.     break;
  568.       case 'f':
  569.     *type += 1;
  570.     if (non_empty)
  571.       string_append (result, " ");
  572.     string_append (result, "float");
  573.     break;
  574.       case 'G':
  575.     *type += 1;
  576.     if (!isdigit (**type))
  577.       {
  578.         success = 0;
  579.         break;
  580.       }
  581.     /* fall through */
  582.       case '0':
  583.       case '1':
  584.       case '2':
  585.       case '3':
  586.       case '4':
  587.       case '5':
  588.       case '6':
  589.       case '7':
  590.       case '8':
  591.       case '9':
  592.     n = 0;
  593.     do
  594.       {
  595.         n *= 10;
  596.         n += **type - '0';
  597.         *type += 1;
  598.       }
  599.     while (isdigit (**type));
  600.     if (strlen (*type) < n)
  601.       {
  602.         success = 0;
  603.         break;
  604.       }
  605.     if (non_empty)
  606.       string_append (result, " ");
  607.     string_appendn (result, *type, n);
  608.     *type += n;
  609.     break;
  610.       default:
  611.     success = 0;
  612.     break;
  613.       }
  614.  
  615.   if (success)
  616.     {
  617.       if (!string_empty (&decl))
  618.     {
  619.       string_append (result, " ");
  620.       string_appends (result, &decl);
  621.     }
  622.       string_delete (&decl);
  623.       return 1;
  624.     }
  625.   else
  626.     {
  627.       string_delete (&decl);
  628.       string_delete (result);
  629.       return 0;
  630.     }
  631. }
  632.  
  633. /* `result' will be initialised in do_type; it will be freed on failure */
  634.  
  635. static int
  636. do_arg (type, result)
  637.      const char **type;
  638.      string *result;
  639. {
  640.   char *tem;
  641.   int len;
  642.   const char *start;
  643.   const char *end;
  644.  
  645.   start = *type;
  646.   if (!do_type (type, result))
  647.     return 0;
  648.   end = *type;
  649.   if (ntypes >= typevec_size)
  650.     {
  651.       if (typevec_size == 0)
  652.     {
  653.       typevec_size = 3;
  654.       typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
  655.     }
  656.       else
  657.     {
  658.       typevec_size *= 2;
  659.       typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
  660.     }
  661.     }
  662.   len = end - start;
  663.   tem = (char *) xmalloc (len + 1);
  664.   memcpy (tem, start, len);
  665.   tem[len] = '\0';
  666.   typevec[ntypes++] = tem;
  667.   return 1;
  668. }
  669.  
  670. /* `decl' must be already initialised, usually non-empty;
  671.    it won't be freed on failure */
  672.  
  673. static int
  674. do_args (type, decl)
  675.      const char **type;
  676.      string *decl;
  677. {
  678.   string arg;
  679.   int need_comma = 0;
  680.  
  681.   string_append (decl, "(");
  682.  
  683.   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
  684.     {
  685.       if (**type == 'N')
  686.     {
  687.       int r;
  688.       int t;
  689.       *type += 1;
  690.       if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
  691.         return 0;
  692.       while (--r >= 0)
  693.         {
  694.           const char *tem = typevec[t];
  695.           if (need_comma)
  696.         string_append (decl, ", ");
  697.           if (!do_arg (&tem, &arg))
  698.         return 0;
  699.           string_appends (decl, &arg);
  700.           string_delete (&arg);
  701.           need_comma = 1;
  702.         }
  703.     }
  704.       else
  705.     {
  706.       if (need_comma)
  707.         string_append (decl, ", ");
  708.       if (!do_arg (type, &arg))
  709.         return 0;
  710.       string_appends (decl, &arg);
  711.       string_delete (&arg);
  712.       need_comma = 1;
  713.     }
  714.     }
  715.  
  716.   if (**type == 'v')
  717.     *type += 1;
  718.   else if (**type == 'e')
  719.     {
  720.       *type += 1;
  721.       if (need_comma)
  722.     string_append (decl, ",");
  723.       string_append (decl, "...");
  724.     }
  725.  
  726.   string_append (decl, ")");
  727.   return 1;
  728. }
  729.  
  730. static void
  731. munge_function_name (name)
  732.      string *name;
  733. {
  734.   if (!string_empty (name) && name->p - name->b >= 3 
  735.       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
  736.     {
  737.       int i;
  738.       /* see if it's an assignment expression */
  739.       if (name->p - name->b >= 10 /* op$assign_ */
  740.       && memcmp (name->b + 3, "assign_", 7) == 0)
  741.     {
  742.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  743.         {
  744.           int len = name->p - name->b - 10;
  745.           if (strlen (optable[i].in) == len
  746.           && memcmp (optable[i].in, name->b + 10, len) == 0)
  747.         {
  748.           string_clear (name);
  749.           string_append (name, "operator");
  750.           string_append (name, optable[i].out);
  751.           string_append (name, "=");
  752.           return;
  753.         }
  754.         }
  755.     }
  756.       else
  757.     {
  758.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  759.         {
  760.           int len = name->p - name->b - 3;
  761.           if (strlen (optable[i].in) == len 
  762.           && memcmp (optable[i].in, name->b + 3, len) == 0)
  763.         {
  764.           string_clear (name);
  765.           string_append (name, "operator");
  766.           string_append (name, optable[i].out);
  767.           return;
  768.         }
  769.         }
  770.     }
  771.       return;
  772.     }
  773.   else if (!string_empty (name) && name->p - name->b >= 5
  774.        && memcmp (name->b, "type$", 5) == 0)
  775.     {
  776.       /* type conversion operator */
  777.       string type;
  778.       const char *tem = name->b + 5;
  779.       if (do_type (&tem, &type))
  780.     {
  781.       string_clear (name);
  782.       string_append (name, "operator ");
  783.       string_appends (name, &type);
  784.       string_delete (&type);
  785.       return;
  786.     }
  787.     }
  788. }
  789.  
  790. /* a mini string-handling package */
  791.  
  792. static void
  793. string_need (s, n)
  794.      string *s;
  795.      int n;
  796. {
  797.   if (s->b == NULL)
  798.     {
  799.       if (n < 32)
  800.     n = 32;
  801.       s->p = s->b = (char *) xmalloc (n);
  802.       s->e = s->b + n;
  803.     }
  804.   else if (s->e - s->p < n)
  805.     {
  806.       int tem = s->p - s->b;
  807.       n += tem;
  808.       n *= 2;
  809.       s->b = (char *) xrealloc (s->b, n);
  810.       s->p = s->b + tem;
  811.       s->e = s->b + n;
  812.     }
  813. }
  814.  
  815. static void
  816. string_delete (s)
  817.      string *s;
  818. {
  819.   if (s->b != NULL)
  820.     {
  821.       free (s->b);
  822.       s->b = s->e = s->p = NULL;
  823.     }
  824. }
  825.  
  826. static void
  827. string_init (s)
  828.      string *s;
  829. {
  830.   s->b = s->p = s->e = NULL;
  831. }
  832.  
  833. static void 
  834. string_clear (s)
  835.      string *s;
  836. {
  837.   s->p = s->b;
  838. }
  839.  
  840. static int
  841. string_empty (s)
  842.      string *s;
  843. {
  844.   return s->b == s->p;
  845. }
  846.  
  847. static void
  848. string_append (p, s)
  849.      string *p;
  850.      const char *s;
  851. {
  852.   int n;
  853.   if (s == NULL || *s == '\0')
  854.     return;
  855.   n = strlen (s);
  856.   string_need (p, n);
  857.   memcpy (p->p, s, n);
  858.   p->p += n;
  859. }
  860.  
  861. static void
  862. string_appends (p, s)
  863.      string *p, *s;
  864. {
  865.   int n;
  866.   if (s->b == s->p)
  867.     return;
  868.   n = s->p - s->b;
  869.   string_need (p, n);
  870.   memcpy (p->p, s->b, n);
  871.   p->p += n;
  872. }
  873.  
  874. static void
  875. string_appendn (p, s, n)
  876.      string *p;
  877.      const char *s;
  878.      int n;
  879. {
  880.   if (n == 0)
  881.     return;
  882.   string_need (p, n);
  883.   memcpy (p->p, s, n);
  884.   p->p += n;
  885. }
  886.  
  887. static void
  888. string_prepend (p, s)
  889.      string *p;
  890.      const char *s;
  891. {
  892.   if (s == NULL || *s == '\0')
  893.     return;
  894.   string_prependn (p, s, strlen (s));
  895. }
  896.  
  897. #if 0
  898. static void
  899. string_prepends (p, s)
  900.      string *p, *s;
  901. {
  902.   if (s->b == s->p)
  903.     return;
  904.   string_prependn (p, s->b, s->p - s->b);
  905. }
  906. #endif
  907.  
  908. static void
  909. string_prependn (p, s, n)
  910.      string *p;
  911.      const char *s;
  912.      int n;
  913. {
  914.   char *q;
  915.  
  916.   if (n == 0)
  917.     return;
  918.   string_need (p, n);
  919.   for (q = p->p - 1; q >= p->b; q--)
  920.     q[n] = q[0];
  921.   memcpy (p->b, s, n);
  922.   p->p += n;
  923. }
  924.